/*
 * Copyright 2000-2009 JetBrains s.r.o. Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions and limitations under the
 * License.
 */
package com.rritw.webtools.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringBufferInputStream;
import java.io.StringReader;
import java.net.URL;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jdom2.xpath.XPath;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

import com.rritw.webtools.common.Const;

/**
 * JDOM工具类
 * 
 * @author ddp1j32
 * @date 2015-2-3
 */
public class JDOMUtil {

    public static Element getElement(String xmlstr) throws JDOMException, IOException {
        StringReader stringReader = new StringReader(xmlstr);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(stringReader);
        Element elem = doc.getRootElement();
        return elem.detach();
    }

    /**
     * 根据指定的xml字符串，生成xml文档对象
     * 
     * @param xmlString XML字符串
     * @return Document 生成的xml文档对象
     * @throws IOException
     * @throws JDOMException
     */
    public static Document getDocument(String xmlString) throws JDOMException, IOException {
        if (StringUtil.isEmpty(xmlString)) {
            return null;
        }
        SAXBuilder builder = new SAXBuilder();
        builder.setEntityResolver(new EntityResolver() {

            // 不做dtd校验，因为没有网络的情况下做dtd校验会报网络异常，可查看博客http://blog.csdn.net/youlianying/article/details/5908335
            @Override
            public InputSource resolveEntity(String publicId, String systemId) {
                return new InputSource(new StringBufferInputStream(""));
            }

        });
        Document anotherDocument = builder.build(new StringReader(xmlString));
        return anotherDocument;

    }

    /**
     * 根据指定的xml文件，生成xml文档对象
     * 
     * @param file xml文件
     * @return Document 生成的xml文档对象
     * @throws IOException
     * @throws JDOMException
     */
    public static Document getDocument(File file) throws JDOMException, IOException {
        SAXBuilder builder = new SAXBuilder();
        Document anotherDocument = builder.build(file);

        return anotherDocument;
    }

    /**
     * 根据输入流，并生成xml文档对象
     * 
     * @param ins InputStream XML输入流
     * @return Document 生成的xml文档对象
     * @throws IOException
     * @throws JDOMException
     */
    public static Document getDocument(InputStream ins) throws JDOMException, IOException {
        SAXBuilder builder = new SAXBuilder();
        Document anotherDocument = builder.build(ins);
        return anotherDocument;
    }

    /**
     * 根据classpath读取文件，并生成xml文档对象
     * 
     * @param classPath
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static Document getDocumentByClassPath(String classPath) throws JDOMException, IOException {
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPath);
        return getDocument(is);
    }

    /**
     * 根据classpath获取XML的内容，以字符串返回
     * 
     * @param classPath
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static String getDocumentStringByClassPath(String classPath) throws JDOMException, IOException {
        return getDocumentStringByClassPath(classPath, Const.CHARSET, Format.getPrettyFormat());
    }

    /**
     * 根据classpath获取XML的内容，以字符串返回
     * 
     * @param classPath
     * @param encode
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static String getDocumentStringByClassPath(String classPath, String encode) throws JDOMException,
                                                                                       IOException {
        return getDocumentStringByClassPath(classPath, encode, Format.getPrettyFormat());
    }

    /**
     * 根据classpath获取XML的内容，以字符串返回
     * 
     * @param classPath
     * @param format
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static String getDocumentStringByClassPath(String classPath, Format format) throws JDOMException,
                                                                                       IOException {
        return getDocumentStringByClassPath(classPath, Const.CHARSET, format);
    }

    /**
     * 根据classpath获取XML的内容，以字符串返回
     * 
     * @param classPath
     * @param encode
     * @param format
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static String getDocumentStringByClassPath(String classPath, String encode,
                                                      Format format) throws JDOMException, IOException {
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPath);
        Document doc = getDocument(is);
        String xmlString = toXML(doc, encode, format);
        return xmlString;
    }

    /**
     * 根据XML文件的地址，创建XML文档对象
     * 
     * @param urlStr String XML文件的地址
     * @return Document 生成的XML文档对象
     * @throws IOException
     * @throws JDOMException
     */
    public static Document getDocumentByURL(String urlStr) throws IOException, JDOMException {
        URL url = new URL(urlStr);
        InputStream ins = url.openStream();
        SAXBuilder builder = new SAXBuilder();
        Document anotherDocument = builder.build(ins);
        return anotherDocument;
    }

    /**
     * 将文档对象转换成xml字符串
     * 
     * @param xmlDoc 文档对象
     * @param encoding 编码
     * @return String Document的xml字符串
     * @throws IOException
     */
    public static String toXML(Document xmlDoc) throws IOException {
        return toXML(xmlDoc, Const.CHARSET, Format.getPrettyFormat());
    }

    /**
     * 将文档对象转换成xml字符串
     * 
     * @param xmlDoc 文档对象
     * @param encoding 编码
     * @return String Document的xml字符串
     * @throws IOException
     */
    public static String toXML(Document xmlDoc, String encoding) throws IOException {
        return toXML(xmlDoc, encoding, Format.getPrettyFormat());
    }

    /**
     * 将文档对象转换成xml字符串
     * 
     * @param xmlDoc
     * @param format
     * @return
     * @throws IOException
     */
    public static String toXML(Document xmlDoc, Format format) throws IOException {
        return toXML(xmlDoc, Const.CHARSET, format);
    }

    /**
     * 将文档对象转换成xml字符串
     * 
     * @param xmlDoc
     * @param encoding
     * @param format
     * @return
     * @throws IOException
     */
    public static String toXML(Document xmlDoc, String encoding, Format format) throws IOException {
        if (xmlDoc == null) {
            return Const.EMPTY_STRING;
        }
        ByteArrayOutputStream byteRep = new ByteArrayOutputStream();
        PrintWriter out = new PrintWriter(byteRep);
        format.setEncoding(encoding);
        XMLOutputter docWriter = new XMLOutputter(format);
        try {
            docWriter.output(xmlDoc, out);
        } catch (Exception e) {
        }
        String xmlString = byteRep.toString();
        return xmlString;
    }

    /**
     * 将文档对象转换成xml字符串
     * 
     * @param xmlDoc
     * @param format
     * @return
     * @throws IOException
     */
    public static String toXML(Element element, Format format) throws IOException {
        return toXML(element, Const.CHARSET, format);
    }

    /**
     * 将文档对象转换成xml字符串
     * 
     * @param xmlDoc
     * @param encoding
     * @param format
     * @return
     * @throws IOException
     */
    public static String toXML(Element element, String encoding, Format format) throws IOException {
        ByteArrayOutputStream byteRep = new ByteArrayOutputStream();
        PrintWriter out = new PrintWriter(byteRep);
        format.setEncoding(encoding);
        XMLOutputter docWriter = new XMLOutputter(format);
        try {
            docWriter.output(element, out);
        } catch (Exception e) {
        }
        String xmlString = byteRep.toString();
        return xmlString;
    }

    /**
     * 根据XPath从文档对象中查找值
     * 
     * @param xmlDoc
     * @param xpath
     * @return
     */
    public static String getValueByXpath(Document xmlDoc, String xpath) {
        String value = "";
        try {
            if (XPath.selectSingleNode(xmlDoc, xpath) == null) {
                value = null;
            } else {
                value = ((Element) (XPath.selectSingleNode(xmlDoc, xpath))).getTextTrim();
            }
        } catch (JDOMException e) {
        }
        return value;
    }

    /**
     * 根据XPath从文档对象中查找值
     * 
     * @param xmlDoc
     * @param xpath
     * @return
     */
    public static String getValueByXpathNotTrim(Document xmlDoc, String xpath) {
        String value = "";
        try {
            if (XPath.selectSingleNode(xmlDoc, xpath) == null) {
                value = null;
            } else {
                value = ((Element) (XPath.selectSingleNode(xmlDoc, xpath))).getText();
            }
        } catch (JDOMException e) {
        }
        return value;
    }
}
